﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;

namespace TestHCPlayM4
{
    public class HCPlayM4
    {
        /// <summary>
        /// 打开播放文件
        /// BOOL PlayM4_OpenFile(LONG nPort,LPSTR sFileName); 
        /// </summary>
        /// <param name="nPort"></param>
        /// <param name="sFileName">文件名，文件不能超过4G或小于4K</param>
        /// <returns></returns>
        [DllImport("PlayCtrl.dll")]
        public static extern bool PlayM4_OpenFile(int nPort, string sFileName);

        /// <summary>
        /// 关闭播放文件
        /// BOOL PlayM4_CloseFile(LONG nPort); 
        /// </summary>
        /// <param name="nPort"></param>
        /// <returns></returns>
        [DllImport("PlayCtrl.dll")]
        public static extern bool PlayM4_CloseFile(int nPort);

        /// <summary>
        /// 播放开始，播放视频画面大小将根据hWnd窗口调整，要全屏显示，只要把hWnd窗口放大到全屏。
        ///     如果已经播放，只是改变当前播放速度为正常速度。 
        ///     输入参数：hWnd 播放视频的窗口句柄。 
        /// BOOL PlayM4_Play(LONG nPort, HWND hWnd); 
        /// </summary>
        /// <param name="nPort"></param>
        /// <param name="hWnd"></param>
        /// <returns></returns>
        [DllImport("PlayCtrl.dll")]
        public static extern bool PlayM4_Play(int nPort, IntPtr hWnd);

        /// <summary>
        /// 播放结束
        /// BOOL PlayM4_Stop(LONG nPort); 
        /// </summary>
        /// <param name="nPort"></param>
        /// <returns></returns>
        [DllImport("PlayCtrl.dll")]
        public static extern bool PlayM4_Stop(int nPort);

        /// <summary>
        /// 播放暂停/恢复
        /// BOOL PlayM4_Pause(LONG nPort,DWORD nPause); 
        /// </summary>
        /// <param name="nPort"></param>
        /// <param name="nPause">TRUE暂停，否则恢复</param>
        /// <returns></returns>
        [DllImport("PlayCtrl.dll")]
        public static extern bool PlayM4_Pause(int nPort, bool nPause);

        /// <summary>
        /// 快速播放，每次调用将使当前播放速度加快一倍，最多调用4次；要恢复正常播放调用
        /// PlayM4_Play(),从当前位置开始正常播放
        /// BOOL Hik_PlayM4_Fast(LONG nPort); 
        /// </summary>
        /// <param name="nPort"></param>
        /// <returns></returns>
        [DllImport("PlayCtrl.dll")]
        public static extern bool PlayM4_Fast(int nPort);

        /// <summary>
        /// 慢速播放，每次调用将使当前播放速度慢一倍；最多调用4次；要恢复正常播放调用Hik_PlayM4_Play
        /// BOOL PlayM4_Slow(LONG nPort); 
        /// </summary>
        /// <param name="nPort"></param>
        /// <returns></returns>
        [DllImport("PlayCtrl.dll")]
        public static extern bool PlayM4_Slow(int nPort);

        /// <summary>
        /// 设置文件播放指针的相对位置（百分比）。 
        /// BOOL PlayM4_SetPlayPos(LONG nPort,float fRelativePos); 
        /// </summary>
        /// <param name="nPort"></param>
        /// <param name="fRelativePos">范围0-100%  0-1 之间</param>
        /// <returns></returns>
        [DllImport("PlayCtrl.dll")]
        public static extern bool PlayM4_SetPlayPos(int nPort, float fRelativePos);

        /// <summary>
        /// 获得文件播放指针的相对位置
        /// float PlayM4_GetPlayPos(LONG nPort); 
        /// </summary>
        /// <param name="nPort">范围0-100%</param>
        /// <returns></returns>
        [DllImport("PlayCtrl.dll")]
        public static extern float PlayM4_GetPlayPos(int nPort);

        /// <summary>
        /// 说明：设置文件结束时要发送的消息；从2.4版开始，当文件播放完时，解码线程将不会自动结束，需要
        /// 用户做停止工作：应用程序在收到这个消息后要调用播放结束函数Hik_PlayM4_Stop(nPort)。 
        /// BOOL PlayM4_SetFileEndMsg(LONG nPort,HWND hWnd,UINT nMsg); 
        /// </summary>
        /// <param name="nPort"></param>
        /// <param name="hWnd">消息发送的窗口。 </param>
        /// <param name="nMsg">用户自定义的输入的消息；当播放到文件结束时用户从hWnd窗口过程中收到这个消息。此消息函数中的wParam参数返回nPort的值。</param>
        /// <returns></returns>
        [DllImport("PlayCtrl.dll")]
        public static extern bool PlayM4_SetFileEndMsg(int nPort, IntPtr hWnd, uint nMsg);

        public struct FRAME_INFO
        {
            /// <summary>
            /// 画面宽，单位像素。如果是音频数据则为0
            /// 
            /// long nWidth;
            /// </summary>
            public int nWidth;
            /// <summary>
            /// 画面高。如果是音频数据则为0
            /// 
            /// long nHeight;
            /// </summary>
            public int nHeight;
            /// <summary>
            /// 时标信息，单位毫秒。
            /// 
            /// long nStamp;
            /// </summary>
            public int nStamp;
            /// <summary>
            /// 数据类型，T_AUDIO16，T_RGB32， T_YV12
            /// 
            /// long nType;
            /// </summary>
            public int nType;
            /// <summary>
            /// 编码时产生的图像帧率。
            /// 
            /// long nFrameRate;
            /// </summary>
            public int nFrameRate;
        }

        /// <summary>
        /// void (CALLBACK* DecCBFun)(long nPort,char * pBuf,long nSize,FRAME_INFO * pFrameInfo, long nReserved1,long nReserved2)
        /// 回调函数指针。不能为 NULL; 
        /// </summary>
        /// <param name="nPort">播放器通道号</param>
        /// <param name="pBuf">解码后的音视频数据</param>
        /// <param name="nSize">解码后的音视频数据pBuf的长度</param>
        /// <param name="pFrameInfo">图像和声音信息</param>
        /// <param name="nReserved1">保留参数</param>
        /// <param name="nReserved2">保留参数</param>
        public delegate void DecCBFun(int nPort, IntPtr pBuf, int nSize, ref FRAME_INFO pFrameInfo, int nReserved1, int nReserved2);

        /// <summary>
        ///  设置回调函数，替换播放器中的显示部分，有用户自己控制显示，该函数在Hik_PlayM4_Play之前调用，
        ///  在PlayM4_Stop时自动失效，下次调用Hik_PlayM4_Play之前需要重新设置。
        ///  注意解码部分不控制速度，只要用户从回调函数中返回，解码器就会解码下一部分数据。这个功能
        ///  的使用需要用户对视频显示和声音播放有足够的了解，否则请慎重使用，有关知识请参阅directx开发包。
        ///  BOOL __stdcall PlayM4_SetDecCallBackMend(LONG nPort,void (CALLBACK* DecCBFun)(long nPort,char * pBuf,long nSize,FRAME_INFO * pFrameInfo, long nUser, long nReserved2), long nUser); 
        /// </summary>
        /// <param name="nPort"></param>
        /// <param name="dcbf">DecCBFun回调函数指针，不能为NULL</param>
        /// <param name="nUser"></param>
        /// <returns></returns>
        [DllImport("PlayCtrl.dll")]
        public static extern bool PlayM4_SetDecCallBack(int nPort, DecCBFun dcbf);

        /// <summary>
        /// 输入从卡上得到的流数据；打开流之后才能输入数据。
        /// BOOL  PlayM4_InputData(LONG nPort,PBYTE pBuf,DWORD nSize); 
        /// </summary>
        /// <param name="nPort"></param>
        /// <param name="pBuf">缓冲区地址</param>
        /// <param name="nSize">缓冲区大小</param>
        /// <returns>TURE,表示已经输入数据。FALSE 表示失败，数据没有输入。</returns>
        [DllImport("PlayCtrl.dll")]
        public static extern bool PlayM4_InputData(int nPort, IntPtr pBuf, uint nSize);

        /// <summary>
        /// void FileRefDone(DWORD nPort,DWORD nUser) 
        /// </summary>
        /// <param name="nPort">播放器通道号</param>
        /// <param name="nUser">用户数据</param>
        public delegate void FileRefDone(int nPort, ushort nUser);

        /// <summary>
        /// 设置回调函数指针，文件索引建立后回调。为了能在文件中准确快速的定位，我们在文件打
        /// 开的时候生成文件索引。这个过程耗时比较长，大约每秒处理40M左右的数据，主要是因为从硬盘
        /// 读数据比较慢。建立索引的过程是在后台完成，需要使用索引的函数要等待这个过程结束，而其他接口不会受到影响。 
        /// BOOL PlayM4_SetFileRefCallBack(LONG nPort,  void (__stdcall *pFileRefDone) (DWORD nPort,DWORD nUser),DWORD nUser); 
        /// </summary>
        /// <param name="nPort"></param>
        /// <param name="frd">回调函数指针</param>
        /// <param name="nUser">用户数据</param>
        /// <returns></returns>
        [DllImport("PlayCtrl.dll")]
        public static extern bool PlayM4_SetFileRefCallBack(int nPort, FileRefDone frd, ushort nUser);

        /// <summary>
        /// void CALLBACK DrawFun(long nPort,HDC hDc,LONG nUser)； 
        /// </summary>
        /// <param name="nPort">通道号</param>
        /// <param name="hDc">hDc OffScreen表面设备上下文，你可以像操作显示窗口客户区DC那样操作它。</param>
        /// <param name="nUser">用户数据，就是上面输入的用户数据</param>
        public delegate void DrawFun(int nPort, IntPtr hDc, int nUser);

        /// <summary>
        /// 注册一个回调函数，获得当前表面的device context, 你可以在这个DC上画图（或写字），就好
        /// 像在窗口的客户区DC上绘图，但这个DC不是窗口客户区的DC，而是DirectDraw里的
        /// Off-Screen表面的DC。注意，如果是使用overlay表面，这个接口无效，你可以直接在窗口上绘图，只要不是透明色就不会被覆盖。 
        /// BOOL __stdcall PlayM4_RigisterDrawFun(LONG nPort,void (CALLBACK* DrawFun)(long nPort,HDC hDc,LONG nUser),LONG nUser); 
        /// </summary>
        /// <param name="nPort"></param>
        /// <param name="df">回调函数句柄。 </param>
        /// <param name="nUser">用户数据</param>
        /// <returns></returns>
        [DllImport("PlayCtrl.dll")]
        public static extern bool Hik_PlayM4_RigisterDrawFun(int nPort, DrawFun df, int nUser);

        /// <summary>
        /// 获取文件索引信息，以便下次打开同一个文件时直接使用这个信息。必须在索引建成后才能获得信息。 
        /// BOOL __stdcall PlayM4_GetRefValue(LONG nPort,BYTE *pBuffer, DWORD *pSize); 
        /// </summary>
        /// <param name="nPort"></param>
        /// <param name="pBuffer">索引信息</param>
        /// <param name="pSize">
        ///     输入/输出参数：输入pBuffer的大小，输出索引信息大小。
        ///     注：可以在第一次指定pSize=0,pBuffer=NULL
        ///     从pSize的返回值获得需要的缓冲区大小。然后分配足够的缓冲，再调用一次 
        /// </param>
        /// <returns></returns>
        [DllImport("PlayCtrl.dll")]
        public static extern bool PlayM4_GetRefValue(int nPort, IntPtr pBuffer, ref ushort pSize);

        /// <summary>
        /// 设置文件索引。如果已经有了文件索引信息，可以不再调用生成索引的回调函数(53.Hik_PlayM4_SetFileRefCallBack)，直接输入索引信息。
        ///     注：索引信息及其长度必须准确 
        /// BOOL __stdcall PlayM4_SetRefValue(LONG nPort,BYTE *pBuffer, DWORD nSize); 
        /// </summary>
        /// <param name="nPort"></param>
        /// <param name="pBuffer">索引信息。</param>
        /// <param name="nSize">索引信息的长度</param>
        /// <returns></returns>
        [DllImport("PlayCtrl.dll")]
        public static extern bool PlayM4_SetRefValue(int nPort, IntPtr pBuffer, ushort nSize);

        /// <summary>
        /// 设置流播放的模式。必须在播放之前设置。 
        ///     注意：2.2版以后可以做暂停，快放，慢放，单帧播放操作。 
        /// BOOL Hik_PlayM4_SetStreamOpenMode(LONG nPort,DWORD nMode); 
        /// </summary>
        /// <param name="nPort"></param>
        /// <param name="nMode">STREAME_REALTIME实时模式（默认），STREAME_FILE文件模式。</param>
        /// <returns></returns>
        [DllImport("PlayCtrl.dll")]
        public static extern bool PlayM4_SetStreamOpenMode(int nPort, ulong nMode);

        /// <summary>
        /// 打开流接口（类似打开文件）
        /// BOOL  PlayM4_OpenStream(LONG nPort,PBYTE pFileHeadBuf,DWORD nSize,DWORD nBufPoolSize); 
        /// </summary>
        /// <param name="nPort"></param>
        /// <param name="pFileHeadBuf">用户从卡上得到的文件头数据。</param>
        /// <param name="nSize">文件头长度。</param>
        /// <param name="nBufPoolSize">设置播放器中存放数据流的缓冲区大小。范围是SOURCE_BUF_MIN~ SOURCE_BUF_MAX。 </param>
        /// <returns></returns>
        [DllImport("PlayCtrl.dll")]
        public static extern bool PlayM4_OpenStream(int nPort, IntPtr pFileHeadBuf, uint nSize, uint nBufPoolSize);
    }
}
